home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / ixemul-complete / ixemul / library / machdep.c < prev    next >
C/C++ Source or Header  |  1996-08-18  |  22KB  |  705 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  machdep.c,v 1.1.1.1 1994/04/04 04:30:40 amiga Exp
  20.  *
  21.  *  machdep.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:40  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.5  1993/11/05  21:59:18  mwild
  26.  *  add code to deal with inet.library
  27.  *
  28.  *  Revision 1.4  1992/10/20  16:25:24  mwild
  29.  *  no nasty 'c' polling in DEF-signalhandler...
  30.  *
  31.  *  Revision 1.3  1992/08/09  20:57:59  amiga
  32.  *  add volatile to sysbase access, or the optimizer takes illegal shortcuts...
  33.  *
  34.  *  Revision 1.2  1992/07/04  19:20:20  mwild
  35.  *  add yet another state in which not to force a context switch.
  36.  *  Probably unnecessary paranoia...
  37.  *
  38.  * Revision 1.1  1992/05/14  19:55:40  mwild
  39.  * Initial revision
  40.  *
  41.  */
  42.  
  43. #define _KERNEL
  44. #include "ixemul.h"
  45. #include <sys/wait.h>
  46. #include "kprintf.h"
  47.  
  48. #include <string.h>
  49. #include <exec/execbase.h>
  50.  
  51. /* jump to pc in supervisor mode, usp is set to USP before */
  52. extern void volatile supervisor (u_int pc, u_int usp);
  53.  
  54. /* context restore functions for 68000 and 68020 rsp */
  55.  
  56. /* takes the sigcontext * from the usp and restores it 
  57.  * Assumes it's called by Supervisor(), ie. with an exception frame
  58.  */
  59. extern void volatile do_sigreturn (void);
  60.  
  61. /*
  62.  * These two are callable with jsr from supervisor mode, and then
  63.  * set up a fake exception frame and call do_sigreturn().
  64.  */
  65. extern void volatile sup00_do_sigreturn_ssp (u_int ssp);
  66. extern void volatile sup00_do_sigreturn (void);
  67. extern void volatile sup00_do_sigresume (void);
  68. extern void volatile restore_00 ();
  69. extern void volatile sup20_do_sigreturn_ssp (u_int ssp);
  70. extern void volatile sup20_do_sigreturn (void);
  71. extern void volatile sup20_do_sigresume (void);
  72. extern void volatile restore_20 ();
  73. /*
  74.  * Either one of sup{00,20}_do_sigreturn, set by configure_context_switch ();
  75.  */
  76. static void volatile (*sup_do_sigresume) (void);
  77. static void volatile (*sup_do_sigreturn) (void);
  78. static void volatile (*sup_do_sigreturn_ssp) (u_int ssp);
  79.  
  80. void setrun (struct Task *t);
  81. void sendsig(struct user *p, sig_t catcher, int sig, int mask, unsigned code, void *addr);
  82.  
  83. struct sigframe {
  84.   int            sf_signum;    /* signo for handler */
  85.   int            sf_code;    /* additional info for handler */
  86.   void            *sf_addr;    /* yet another info for handler ;-)) */
  87.   sig_t            sf_handler;    /* handler addr for u_sigc */
  88.   struct sigcontext     sf_sc;        /* actual context */
  89. };
  90.  
  91.  
  92. void
  93. configure_context_switch (void)
  94. {
  95.   if (betterthan68000())
  96.     {
  97.       sup_do_sigresume = sup20_do_sigresume;
  98.       sup_do_sigreturn = sup20_do_sigreturn;
  99.       sup_do_sigreturn_ssp = sup20_do_sigreturn_ssp;
  100.     }
  101.   else
  102.     {
  103.       sup_do_sigresume = sup00_do_sigresume;
  104.       sup_do_sigreturn = sup00_do_sigreturn;
  105.       sup_do_sigreturn_ssp = sup00_do_sigreturn_ssp;
  106.     }
  107. }
  108.  
  109. void volatile
  110. sigreturn (struct sigcontext *sc)
  111. {
  112.   supervisor ((u_int) do_sigreturn, (u_int) sc);
  113. }
  114.  
  115. void volatile
  116. sig_trampoline (struct sigframe sf)
  117. {
  118.   if (u.u_a4)
  119.     asm ("movel %0,a4" : : "g" (u.u_a4));
  120.   ((void (*)())sf.sf_handler) (sf.sf_signum, sf.sf_code, sf.sf_addr, & sf.sf_sc);
  121.  
  122.   sigreturn (& sf.sf_sc);
  123. }
  124.  
  125. /*
  126.  * This one is executed in Supervisor mode, just before dispatching this
  127.  * task, so be as quick as possible here !
  128.  */
  129. void
  130. sig_launch (void) 
  131. {
  132.   struct Task         *me         = SysBase->ThisTask;
  133.   /* precalculate struct user, so we don't have to go thru SysBase all the time */
  134.   struct user         *p         = (struct user *) me->tc_TrapData;
  135.   sigset_t         sigmsg         = sigmask (SIGMSG);
  136.   sigset_t        sigint         = sigmask (SIGINT);
  137.   sigset_t         newsigs;
  138.   int             i;
  139.   u_int            usp = 0, orig_usp;
  140.   struct sigcontext     *sc;
  141.   u_int            ret_pc, ret_ssp;
  142.  
  143.   /* GCC supports nested functions, and that's just what I need! */
  144.  
  145.   void setup_sigcontext(void)
  146.   {
  147.     usp = orig_usp = get_usp () + 8;     /* set up by our glue_launch() stub */
  148.     
  149.     /* the glue passes us the values of the pc and ssp to restore, if we should
  150.      * decide to sup_do_sigreturn_ssp() out of here, instead of leaving harmlessly..
  151.      */
  152.     ret_pc  = ((u_int *)usp)[-2];
  153.     ret_ssp = ((u_int *)usp)[-1];
  154.     
  155.     /* push a sigcontext that will get us back if no other signals
  156.      * were produced */
  157.     usp -= sizeof (struct sigcontext);
  158.     sc = (struct sigcontext *) usp;
  159.     set_usp (usp);
  160.     
  161.     sc->sc_onstack = p->u_onstack;
  162.     sc->sc_mask     = p->p_sigmask;
  163.     sc->sc_sp     = orig_usp;
  164.  
  165.     /* the OS context restore function expects a5 to contain the usp, so
  166.      * we have to obey.. */
  167.     sc->sc_fp     = orig_usp;
  168.     sc->sc_ap     = *(u_int *)&me->tc_Flags;
  169.     sc->sc_pc     = ret_pc;
  170.     sc->sc_ps     = get_sr();
  171.   
  172.     p->u_regs = NULL;
  173.     p->u_fpregs = NULL;
  174.   };
  175.  
  176.   if (p->u_mask_state) /* do not handle signals while the stop-handler is running */
  177.     return;
  178.  
  179.   /* if we're inside ix_sleep, no signal processing is done to break the
  180.      Wait there as soon as possible. Signals resume on return of ix_sleep */
  181.   /* Likewise if the process is stopped for debugging (SSTOP).  */
  182.   if (p->p_stat == SSLEEP || p->p_stat == SSTOP)
  183.     return;
  184.  
  185.   /* special processing for Wait()ing in Commodore inet.library. They
  186.      do reasonable interrupt checking, but only on SIGBREAKF_CTRL_C. So
  187.      whenever we have a signal to deliver, send ^C.. */
  188.   if (p->p_stat == SWAIT)
  189.     {
  190.       setup_sigcontext();
  191.       if (CURSIG (p))
  192.         Signal (me, SIGBREAKF_CTRL_C);
  193.       goto out;
  194.     }
  195.  
  196.   /* smells kludgy I know...... */
  197.   if (me->tc_TDNestCnt >= 0 || me->tc_IDNestCnt >= 0)
  198.     return;
  199.  
  200.   setup_sigcontext();
  201.  
  202.   /*
  203.    * first check amigados signals. If SIGMSG is set to SIG_IGN or SIG_DFL, 
  204.    * we do our default mapping of SIGBREAKF_CTRL_C into SIGINT.
  205.    */
  206.   newsigs      = me->tc_SigRecvd & ~p->u_lastrcvsig;
  207.   p->u_lastrcvsig = me->tc_SigRecvd;
  208.  
  209.   if (p->u_ixnetbase)
  210.     netcall(NET__siglaunch, newsigs);
  211.  
  212.   if (((p->p_sigignore & sigmsg) || !(p->p_sigcatch & sigmsg)) 
  213.       && (newsigs & SIGBREAKF_CTRL_C))
  214.     {
  215.       /* in that case send us a SIGINT, if it's not ignored */
  216.       if (!(p->p_sigignore & sigint))
  217.           _psignalgrp((struct Process *)me, SIGINT);
  218.         
  219.       /* in this mode we fully handle and use SIGBREAKF_CTRL_C, so remove it
  220.        * from the Exec signal mask */
  221.        
  222.       me->tc_SigRecvd &= ~SIGBREAKF_CTRL_C;
  223.       p->u_lastrcvsig &= ~SIGBREAKF_CTRL_C;
  224.     }
  225.   else if (newsigs && (p->p_sigcatch & sigmsg))
  226.     {
  227.       /* if possible, deliver the signal directly to get a code argument */
  228.       if (!(p->p_flag & STRC) && !(p->p_sigmask & sigmsg))
  229.         {
  230.           p->u_ru.ru_nsignals++;
  231.           sendsig(p, p->u_signal[SIGMSG], SIGMSG, p->p_sigmask, newsigs, 0);
  232.           p->p_sigmask |= p->u_sigmask[SIGMSG] | sigmsg;
  233.           setrun (me);
  234.         }
  235.       else
  236.         _psignal (me, SIGMSG);
  237.     }
  238.  
  239.   /* stack watch.. NEVER do this when vforked, the sp is out of bounds then.. */
  240.   if ((ix.ix_flags & ix_watch_stack) && p->u_red_zone && !p->p_vfork_msg && !p->u_onstack)
  241.     {
  242.       if (((void *) usp) < p->u_red_zone)
  243.         _psignal (me, SIGSEGV);
  244.     }
  245.  
  246.   if ((i = CURSIG(p)))
  247.     {
  248.       psig (p, i);
  249.     }
  250.  
  251. out:
  252.   /* now try to optimize. We could always call sup_do_sigreturn here, but if no
  253.    * signals generated frames, we can just as well simply return, after having
  254.    * restored our usp */
  255.   if (usp == get_usp ())
  256.     {
  257.       /* this is probably not even necessary, since after processing sig_launch
  258.        * the OS reinstalls the usp as me->tc_SPReg, but I guess it's cleaner to
  259.        * do it explicitly here, to show that we reset usp to what it was before
  260.        */
  261.       set_usp (orig_usp);
  262.       return;
  263.     }
  264.   sup_do_sigreturn_ssp (ret_ssp);
  265. }
  266.  
  267.  
  268. void
  269. switch_glue (void)
  270. {
  271. }
  272.  
  273. /*
  274.  * Send an interrupt to process.
  275.  * Called from psig() which is called from sig_launch, thus we are in
  276.  * SUPERVISOR .
  277.  */
  278. void
  279. sendsig (struct user *p, sig_t catcher, int sig, int mask, unsigned code, void *addr)
  280. {
  281.   struct Task        *me        = SysBase->ThisTask;
  282.   u_int         usp, orig_usp;
  283.   struct sigframe     *sf;
  284.   struct sigcontext    *sc;
  285.   int            oonstack;
  286.   int            to_stopped_handler = (catcher == (sig_t)stopped_process_handler);
  287.   int             *dummy_frame;
  288.  
  289.   orig_usp = get_usp();    /* get value to restore later */
  290.  
  291.   oonstack = p->u_onstack;
  292.  
  293.   if (!p->u_onstack && (p->u_sigonstack & sigmask(sig)))
  294.     {
  295.       p->u_onstack = 1;
  296.       usp = (u_int) p->u_sigsp;
  297.     }
  298.   else
  299.     usp = orig_usp;
  300.   
  301.   /* make room for dummy stack frame (used by GDB) */
  302.   usp -= 8;
  303.   dummy_frame = (int *)usp;
  304.   /* push signal frame */
  305.   usp -= sizeof (struct sigframe);
  306.   sf = (struct sigframe *) usp;
  307.   
  308.   /* fill out the frame */
  309.   sf->sf_signum        = sig;
  310.   sf->sf_code          = code;
  311.   sf->sf_addr           = addr;
  312.   sf->sf_handler       = catcher;
  313.   sf->sf_sc.sc_onstack = oonstack;
  314.   sf->sf_sc.sc_mask    = mask;
  315.   sf->sf_sc.sc_sp      = (int) orig_usp;    /* previous sigcontext */
  316.   sf->sf_sc.sc_fp      = p->u_regs ? p->u_regs->r_regs[13] : 0;
  317.   sf->sf_sc.sc_ap      = *(u_int *)&me->tc_Flags;
  318.   sf->sf_sc.sc_ps      = get_sr() & ~0x8000;    /* we're in supervisor then */
  319.   /* this pc will restore it */
  320.   sf->sf_sc.sc_pc      = (int)(to_stopped_handler ? sup_do_sigresume : sup_do_sigreturn);
  321.  
  322.   /* push a signal context to call sig_trampoline */
  323.   usp -= sizeof (struct sigcontext);
  324.   sc = (struct sigcontext *) usp;
  325.  
  326.   /*
  327.    * NOTE: we set the default of a handler to Permit(), Enable(). I guess this
  328.    *       makes sense, since if either Forbid() or Disable() is active, it
  329.    *       shouldn't be possible to invoke a signal anyway, EXCEPT if the
  330.    *       task is Wait()ing, then the OS calls Switch() directly while
  331.    *       either Disable() or Forbid() is active (depends on OS version).
  332.    */
  333.  
  334.   sc->sc_onstack = p->u_onstack;
  335.   sc->sc_mask    = p->p_sigmask;
  336.   sc->sc_sp     = ((int) sf) - 4; /* so that sp@(4) is the argument */
  337.   dummy_frame[0] = (int)(p->u_regs ? p->u_regs->r_regs[13] : 0);
  338.   dummy_frame[1] = (int)(p->u_regs ? p->u_regs->r_pc : 0);
  339.   sc->sc_fp     = (int)dummy_frame;
  340.   sc->sc_ap     = (me->tc_Flags << 24) | (me->tc_State << 16) |
  341.              ((u_char)(-1) << 8) | (u_char)(-1);
  342.   sc->sc_ps     = ((to_stopped_handler || !p->u_regs) ? 0 : (p->u_regs->r_sr & ~0x2000));
  343.   sc->sc_pc     = (int) sig_trampoline;
  344.   
  345.   set_usp (usp);
  346. }
  347.  
  348.  
  349. /*
  350.  * called as the default action of a signal that terminates the process
  351.  */
  352. void
  353. sig_exit (unsigned int code)
  354. {
  355.   /* the whole purpose of this code inside is to
  356.    * prettyprint and identify the job that just terminates
  357.    * This stuff should be handled by a shell, but since there's (yet) no
  358.    * shell that knows how to interpret a signal-exit code I have to do it
  359.    * here myself...
  360.    */
  361.  
  362.   extern char *sys_siglist[NSIG];
  363.   extern void exit2(int);
  364.   struct Process *me = (struct Process *)(SysBase->ThisTask);
  365.   char err_buf[255];
  366.   struct CommandLineInterface *cli;
  367.   char process_name[255];
  368.   int is_fg;
  369.  
  370.   /* make sure we're not interrupted in this last step.. */
  371.   u.p_flag &= ~STRC;    /* disable tracing */
  372.   syscall (SYS_sigsetmask, ~0);
  373.   if ((ix.ix_flags & ix_create_enforcer_hit) && betterthan68010())
  374.     {
  375.       /* This piece of assembly will skip all the saved registers, signal
  376.      contexts, etc. on the stack and set the stack pointer accordingly.
  377.      The number 700 has been determined by experimenting. After setting
  378.      the SP it will put the exit code into the address 0xDEADDEAD. This
  379.      creates an Enforcer hit, and Enforcer will show a stack dump starting
  380.      with the new SP. If we didn't add 700 bytes to the SP, then you would
  381.      have to configure Enforcer to use a stacktrace of more than 24 lines
  382.      before you would get to the relevant parts of the trace. After that we
  383.      add a nop and restore the SP. The nop was needed because due to the
  384.      pipelining of a 68040 the SP was already updated before Enforcer could
  385.      read the value of the SP. More nops may be needed for the 68060 CPU. */
  386.  
  387.       asm ("movel %0,d0
  388.             addw  #700,sp
  389.             movel d0,0xdeaddead
  390.             nop
  391.             addqw #2,sp
  392.             movel d0,0xdeaddead
  393.             nop
  394.             addaw #-702,sp" : /* no output */ : "a" (code));
  395.     }
  396.   
  397.   /* output differs depending on
  398.    *  o  whether we're a CLI or a WB process (stderr or requester)
  399.    *  o  whether this is a foreground or background process
  400.    *  o  whether this is SIGINT or not
  401.    */
  402.  
  403.   if ((cli = BTOCPTR (me->pr_CLI)))
  404.     {
  405.       char *tmp = BTOCPTR (cli->cli_CommandName);
  406.       int   len = *tmp++;
  407.       
  408.       if (len > sizeof (process_name) - 1)
  409.         len = sizeof (process_name) - 1;
  410.       
  411.       bcopy (tmp, process_name, len);
  412.       process_name[len] = 0;
  413.       
  414.       is_fg = cli->cli_Interactive && !cli->cli_Background;
  415.  
  416.     }
  417.   else
  418.     {
  419.       process_name[0] = 0;
  420.       if (me->pr_Task.tc_Node.ln_Name)
  421.         strncpy (process_name, me->pr_Task.tc_Node.ln_Name, sizeof (process_name) - 1);
  422.         
  423.       /* no WB process is ever considered fg */
  424.       is_fg = 0;
  425.  
  426.     }
  427.  
  428.   /* if is_fg and SIGINT, simulate tty-driver and display ^C */
  429.   if (!(is_fg && (code == SIGINT)))
  430.     {
  431.       strcpy (err_buf, (code < NSIG) ? sys_siglist[code] : "Unknown signal");
  432.  
  433.       /* if is_fg, don't display the job */
  434.       if (! is_fg)
  435.         {
  436.           strcat (err_buf, " - ");
  437.       strcat (err_buf, process_name);
  438.           /* if we're a CLI we have an argument line saved, that we can print
  439.            * as well */
  440.       if (cli)
  441.               {
  442.           int line_len;
  443.           char *cp;
  444.           
  445.           /* we can display upto column 77, this should be save on all normal
  446.            * amiga CLI windows */
  447.           line_len = 77 - strlen (err_buf) - 1;
  448.           if (line_len > u.u_arglinelen)
  449.             line_len = u.u_arglinelen;
  450.  
  451.           if (line_len > 0 && u.u_argline)
  452.             {
  453.               strcat (err_buf, " ");
  454.           strncat (err_buf, u.u_argline, line_len);
  455.         }
  456.  
  457.           /* now get rid of possible terminating line feeds/cr's */
  458.           for (cp = err_buf; *cp && *cp != '\n' && *cp != '\r'; cp++) ;
  459.           *cp = 0;
  460.         }
  461.     }
  462.  
  463.       if (cli)
  464.         {
  465.           /* uniformly append ONE line feed */
  466.       strcat (err_buf, "\n");
  467.           syscall (SYS_write, 2, err_buf, strlen (err_buf));
  468.         }
  469.       else
  470.         ix_panic (err_buf);
  471.     }
  472.   else
  473.     syscall (SYS_write, 2, "^C\n", 3);
  474.  
  475.   exit2(W_EXITCODE(0, code));
  476.   /* not reached */
  477. }
  478.  
  479. /*
  480.  * This is used to awaken a possibly sleeping sigsuspend()
  481.  * and to force a context switch, if we send a signal to ourselves
  482.  */
  483. void
  484. setrun (struct Task *t)
  485. {
  486.   struct user *p = (struct user *) t->tc_TrapData;
  487.   u_int curr_disp;
  488.   u_int    sr;
  489.  
  490.   /* NOTE: the context switch is done to make sure sig_launch() is called as
  491.    *       soon as possible in the respective task. It's not nice if you can
  492.    *       return from a kill() to yourself, before the signal handler had a
  493.    *       chance to react accordingly to the signal..
  494.    */
  495.   asm volatile (" 
  496.     movel a5,a0
  497.     lea      L_get_sr,a5
  498.     movel 4:w,a6
  499.     jsr      a6@(-0x1e)
  500.     movel a1,%0
  501.     bra      L_skip
  502. L_get_sr:
  503.     movew sp@,a1    | get sr register from the calling function
  504.     rte
  505. L_skip:
  506.     movel a0,a5
  507.     " : "=g" (sr) : : "a0", "a1", "a6");
  508.  
  509.   /* Don't force context switch if:
  510.      o  running in Supervisor mode
  511.      o  we setrun() some other process
  512.      o  running under either Forbid() or Disable() */
  513.   if ((sr & 0x2000)
  514.       || SysBase->ThisTask != t
  515.       || p->p_stat == SSLEEP
  516.       || p->p_stat == SWAIT
  517.       || p->p_stat == SSTOP
  518.       || SysBase->TDNestCnt >= 0
  519.       || SysBase->IDNestCnt >= 0)
  520.     {
  521.       extern int select();
  522.  
  523.       /* make testing of p_stat and reaction atomic */
  524.       Forbid();
  525.  
  526.       if (p->p_stat == SWAIT)
  527.         Signal (t, SIGBREAKF_CTRL_C);
  528.       else if (p->p_stat == SSTOP)
  529.         {
  530.           p->p_stat = SRUN;
  531.       Signal (t, 1 << p->p_zombie_sig);
  532.         }
  533.       else if (p->p_wchan == (caddr_t) p)
  534.     {
  535.       KPRINTF (("setrun $%lx\n", p));
  536.           ix_wakeup ((u_int)p);
  537.         }
  538.       else if (p->p_wchan == (caddr_t) select)
  539.         Signal (t, 1<<p->u_sleep_sig);
  540.         
  541.       Permit();
  542.       return;
  543.     }
  544.   /* this quite brute-force method, but the only thing I could think of that
  545.    * really guarantees that there was a context switch.. */
  546.  
  547.   /* But I can think of something better: install a high-priority task when
  548.    * the library is opened. That task always Wait()s on signal 1 << 31. So
  549.    * when we want to make a context switch, we signal that task. Because of
  550.    * the high priority of that task, exec.library switches to that task.
  551.    * That task goes immediately back to Waiting for a signal, so
  552.    * exec.library will go back to another task.
  553.    *
  554.    * Just in case this task has also a high priority, we keep around the
  555.    * old method too. */
  556.   curr_disp = SysBase->DispCount;
  557.   Signal(ix.ix_task_switcher, 1 << 31);  /* signal the task switcher */
  558.   while (curr_disp == ((volatile struct ExecBase *)SysBase)->DispCount) ;
  559. }
  560.  
  561. /*
  562.  * Mapping from vector numbers into signals
  563.  */
  564. const static int hwtraptable[256] = {
  565.   SIGILL, /* Reset initial stack pointer */
  566.   SIGILL, /* Reset initial program counter */
  567.   SIGBUS, /* Bus Error */
  568.   SIGBUS, /* Address Error */
  569.   SIGILL, /* Illegal Instruction */
  570.   SIGFPE, /* Zero Divide */
  571.   SIGFPE, /* CHK, CHK2 Instruction */
  572.   SIGFPE, /* cpTRAPcc, TRAPcc, TRAPV Instruction */
  573.   SIGILL, /* Privilege Violation */
  574.   SIGTRAP,/* Trace */
  575.   SIGEMT, /* Line 1010 Emulator */
  576.   SIGEMT, /* Line 1111 Emulator */
  577.   SIGILL,
  578.   SIGILL, /* Coprocessor Protocol Violation */
  579.   SIGILL, /* Format Error */
  580.   SIGILL, /* Uninitialized Interrupt */
  581.   SIGILL, /* 16 */
  582.   SIGILL, /* 17 */
  583.   SIGILL, /* 18 */
  584.   SIGILL, /* 19 */        /* unimplemented, reserved */
  585.   SIGILL, /* 20 */
  586.   SIGILL, /* 21 */
  587.   SIGILL, /* 22 */
  588.   SIGILL, /* 23 */
  589.   SIGILL, /* spurious Interrupt */
  590.   SIGILL, /* Level 1 Interrupt Autovector */
  591.   SIGILL, /* Level 2 Interrupt Autovector */
  592.   SIGILL, /* Level 3 Interrupt Autovector */
  593.   SIGILL, /* Level 4 Interrupt Autovector */
  594.   SIGILL, /* Level 5 Interrupt Autovector */
  595.   SIGILL, /* Level 6 Interrupt Autovector */
  596.   SIGILL, /* Level 7 Interrupt Autovector */
  597.   SIGTRAP, /* Trap #0 (not available on Unix) */
  598.   SIGTRAP, /* Trap #1 */
  599.   SIGILL, /* Trap #2 */
  600.   SIGILL, /* Trap #3 */
  601.   SIGILL, /* Trap #4 */
  602.   SIGILL, /* Trap #5 */
  603.   SIGILL, /* Trap #6 */
  604.   SIGILL, /* Trap #7 */
  605.   SIGILL, /* Trap #8 */
  606.   SIGILL, /* Trap #9 */
  607.   SIGILL, /* Trap #10 */
  608.   SIGILL, /* Trap #11 */
  609.   SIGILL, /* Trap #12 */
  610.   SIGILL, /* Trap #13 */
  611.   SIGILL, /* Trap #14 */
  612.   SIGILL, /* Trap #15 (not available on Unix) */
  613.   SIGFPE, /* FPCP Branch or Set on Unordererd Condition */
  614.   SIGFPE, /* FPCP Inexact Result */
  615.   SIGFPE, /* FPCP Divide by Zero */
  616.   SIGFPE, /* FPCP Underflow */
  617.   SIGFPE, /* FPCP Operand Error */
  618.   SIGFPE, /* FPCP Overflow */
  619.   SIGFPE, /* FPCP Signaling NAN */
  620.   SIGILL,
  621.   SIGBUS, /* MMU Configuration Error */
  622.   SIGILL, /* MMU Illegal Operation (only 68851) */
  623.   SIGILL, /* MMU Privilege Violation (only 68851) */
  624.   /* rest undefined or free user-settable.. */
  625. };
  626.  
  627. /*
  628.  * handle traps handed over from the lowlevel trap handlers
  629.  */
  630. void
  631. trap (void)
  632. {
  633.   u_int            format;
  634.   void            *addr;
  635.   struct reg        *regs;
  636.   struct fpreg        *fpregs;
  637.   struct Task         *me         = SysBase->ThisTask;
  638.   /* precalculate struct user, so we don't have to go thru SysBase all the time */
  639.   struct user         *p         = (struct user *) me->tc_TrapData;
  640.   int             sig;
  641.   u_int            usp, orig_usp;
  642.   struct sigcontext     *sc;
  643.   u_int            ret_pc, ret_ssp;
  644.   extern long        vector_old_pc;
  645.   extern long        vector_nop;
  646.  
  647.   usp = orig_usp = get_usp () + 8;    /* skip argument parameters */
  648.   format = ((u_int *)usp)[0];
  649.   addr = (void *)((u_int *)usp)[1];
  650.   regs = (struct reg *)((u_int *)usp)[2];
  651.   fpregs = (struct fpreg *)((u_int *)usp)[3];
  652.  
  653.   ret_pc  = ((u_int *)usp)[-2];
  654.   ret_ssp = ((u_int *)usp)[-1];
  655.   
  656.   /* push a sigcontext that will get us back here if no other signals
  657.    * were produced */
  658.   usp -= sizeof (struct sigcontext);
  659.   sc = (struct sigcontext *) usp;
  660.   set_usp (usp);
  661.   sc->sc_onstack = p->u_onstack;
  662.   sc->sc_mask     = p->p_sigmask;
  663.   sc->sc_sp     = orig_usp;
  664.   sc->sc_fp     = regs->r_regs[13];
  665.   sc->sc_ap     = *(u_int *)&me->tc_Flags;
  666.   sc->sc_pc     = ret_pc;
  667.   sc->sc_ps     = get_sr() & ~0x8000;
  668.  
  669.   if (regs->r_pc == (void *)(&vector_nop) + 2)
  670.     {
  671.       regs->r_pc = (void *)vector_old_pc;
  672.       vector_old_pc = 0;
  673.     }
  674.   p->u_regs = regs;
  675.   p->u_fpregs = fpregs;
  676.   /* format contains the vector * 4, in the lower 12 bits */
  677.   sig = *(int *)((u_char *)hwtraptable + (format & 0x0fff));
  678.   
  679.   if (sig == SIGTRAP)
  680.     regs->r_sr &= ~0x8000;    /* turn off the trace flag */
  681.  
  682.   trapsignal (me, sig, format, addr);
  683.  
  684.   if ((sig = CURSIG(p)))
  685.     psig (p, sig);
  686.  
  687.   /* now try to optimize. We could always call sup_do_sigreturn here, but if no
  688.    * signals generated frames, we can just as well simply return, after having
  689.    * restored our usp */
  690.   if (usp == get_usp ())
  691.     {
  692.       set_usp (orig_usp);
  693.       return;
  694.     }
  695.   sup_do_sigreturn_ssp (ret_ssp);
  696. }
  697.  
  698. void resume_signal_check(void)
  699. {
  700.   int sig;
  701.  
  702.   if ((sig = issig(&u)))  /* always go through issig if we restart the process */
  703.     psig (&u, sig);
  704. }
  705.